package com.xquant.marketdata.curvestrip.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageInfo;
import com.xquant.common.core.constant.Constants;
import com.xquant.common.redis.service.RedisService;
import com.xquant.common.security.utils.SecurityUtils;
import com.xquant.marketdata.curvestrip.domain.DivIrCurveDTO;
import com.xquant.marketdata.curvestrip.domain.DivIrCurveStripDTO;
import com.xquant.marketdata.curvestrip.domain.IrCurveSetDTO;
import com.xquant.marketdata.curvestrip.domain.IrCurveStripDTO;
import com.xquant.marketdata.curvestrip.entity.TdivyieldRatesDTO;
import com.xquant.marketdata.curvestrip.mapper.DictMapper;
import com.xquant.marketdata.curvestrip.mapper.DivIrCurveStripMapper;
import com.xquant.marketdata.curvestrip.service.DivIrCurveStripService;
import com.xquant.marketdata.utils.DateUtils;
import com.xquant.marketdata.utils.SortUtil;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xpp
 * @version 1.0
 * @date 2020/9/22 13:31
 */
@Service(DivIrCurveStripService.BEAN_NAME)
public class DivIrCurveStripServiceImpl implements DivIrCurveStripService {

    @Autowired
    private DivIrCurveStripMapper divIrCurveStripMapper;
    @Autowired
    private DictMapper dictMapper;
    @Autowired
    private RedisService redisService;

    @Override
    /*查询红利率曲线*/
    public List<DivIrCurveDTO> queryDivIrCurveByPage(Map map) {

        List<DivIrCurveDTO> list = divIrCurveStripMapper.queryDivIrCurveByPage(map);
        return list;
    }

    /*查询红利率曲线样本点*/
    @Override
    public PageInfo<Map> queryDivIrCurveRefSetByPage(Map map) {
        List<Map> list = divIrCurveStripMapper.queryDivIrCurveRefSetByPage(map);
        return new PageInfo<>(list);
    }

    @Override
    public List<DivIrCurveStripDTO> queryDivIrCurveRatesByPage(Map map) {
        Map divMap = divIrCurveStripMapper.queryDivIrCurve(map);
        List<String> tableList = redisService.getDimCacheObject(Constants.SYS_CONFIG_KEY + "*" + Constants.SYS_TABLE_MARKET_KEY + divMap.get("U_A_TYPE"));
        if (tableList.size() == 1) {
            map.put("marketTable", redisService.getCacheObject(tableList.get(0)));
        } else {
            map.put("marketTable", "xir_md.vdaily_price");
        }
        List<Map> list = divIrCurveStripMapper.queryDivIrCurveRatesByPage(map);
        List<Map> maps = SortUtil.sortTerm(list, "div_term", true);
        String refDate = MapUtils.getString(map, "refSetDate");
        for (Map m : maps) {
            m.put("limit_date", DateUtils.addTerm(refDate, MapUtil.getStr(m, "div_term")));
            m.put("div_rate", NumberUtil.round(MapUtil.getStr(m, "div_rate"), 6));
        }
        if (maps.size() > 0) {
            Map queryMap = new HashMap();
            queryMap.put("mType", "CCFX");
            queryMap.put("refSetDate", MapUtil.getStr(map, "refSetDate"));
            queryMap.put("uICode", list.get(0).get("i_code"));
            queryMap.put("uAType", list.get(0).get("a_type"));
            queryMap.put("uMType", list.get(0).get("m_type"));
            List<Map> futureList = divIrCurveStripMapper.queryFutureClose(queryMap);
            for (int i = 0; i < futureList.size(); i++) {
                //红利曲线增加期货价格
                maps.get(i).put("future_close", futureList.get(i).get("dp_close"));
                //基差率=（期货-现货）/现货
                maps.get(i).put("spred", NumberUtil.div(NumberUtil.sub(futureList.get(i).get("dp_close").toString(), maps.get(0).get("dp_close").toString()).toString(), maps.get(i).get("dp_close").toString()));
            }
        }

        List<DivIrCurveStripDTO> resultList = new ArrayList<>();
        for (Map res : maps) {
            DivIrCurveStripDTO divIrCurveStripDTO = BeanUtil.fillBeanWithMap(res, new DivIrCurveStripDTO(), false);
            resultList.add(divIrCurveStripDTO);
        }
//         List<DivIrCurveStripDTO> resultList = maps.stream().map(m -> JSON.parseObject(JSON.toJSONString(m), DivIrCurveStripDTO.class)).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public List<DivIrCurveDTO> getDivIrCurveMx(Map map) {
        return divIrCurveStripMapper.queryDivIrCurveByPage(map);
    }

    /*
     * 修改红利率曲线
     * */
    @Override
    public void updateDivIrCurve(Map map) {
        divIrCurveStripMapper.updateDivIrCurve(map);
    }

    /*
     * 插入红利率曲线
     * */
    @Override
    public void insertDivIrCurve(Map map) {
        map.put("createBy",SecurityUtils.getUserId());
        map.put("pipeId","-1");
        divIrCurveStripMapper.insertDivIrCurve(map);
    }

    /*
     * 删除红利率曲线
     * */
    @Override
    public void deleteDivIrCurve(Map map) {
        map.put("userId", SecurityUtils.getUserId());
        divIrCurveStripMapper.deleteDivIrCurve(map);
        divIrCurveStripMapper.deleteAllDivIrCurveRates(map);
        //删除用户和部门权限表数据
        divIrCurveStripMapper.removeUserPermCurve(map);
        divIrCurveStripMapper.removeDeptPermCurve(map);
        //删除读写权限表数据
        divIrCurveStripMapper.removeUserCurveByDivCode(map);
        divIrCurveStripMapper.removeDeptCurveByDivCode(map);
    }

    /*
     * 修改红利率曲线样本点
     * */
    @Override
    public void updateDivIrCurveRefSet(Map map) {
        divIrCurveStripMapper.updateDivIrCurveRefSet(map);
    }

    @Override
    public void updateDivIrCurveRates(Map map) {
        divIrCurveStripMapper.updateDivIrCurveRates(map);
    }

    @Override
    public void insertDivIrCurveRefSetByDate(Map map) {

    }

    @Override
    public void deleteDivIrCurveRefSetByDate(Map map) {

    }

    @Override
    public int queryDivIrCurveRefSetByDate(Map map) {
        return 0;
    }

    /*插入红利率曲线样本点*/
    @Override
    public void insertDivIrCurveRefSet(Map map) {
        divIrCurveStripMapper.deleteDivIrCurveRates(map);
        divIrCurveStripMapper.insertDivIrCurveRates(map);
    }

    @Override
    public void insertDivIrCurveRates(Map map) {
        map.put("divId",DateUtils.getCurr_YYYYMMDDHHMMSSSSS().substring(2,6) + RandomUtil.randomNumbers(4));
        Map divMap = divIrCurveStripMapper.getLastDay(map);
        if (divMap!=null) {
            divMap.put("END_DATE",map.get("begDate"));
            divIrCurveStripMapper.updateLastDay(divMap);
        }
        Map next = divIrCurveStripMapper.getNextDayByBegDate(map);
        if (next!=null) {
            map.put("endDate",next.get("BEG_DATE"));
        }
        divIrCurveStripMapper.deleteDivIrCurveRates(map);
        divIrCurveStripMapper.insertDivIrCurveRates(map);
    }

    /*删除红利率曲线样本点*/
    @Override
    public void deleteDivIrCurveRefSet(Map map) {
        divIrCurveStripMapper.deleteDivIrCurveRefSet(map);
    }

    @Override
    public void deleteDivIrCurveRates(Map map) {
        divIrCurveStripMapper.deleteDivIrCurveRates(map);
    }

    @Override
    public void deleteAllDivIrCurveRefSet(Map map) {

    }

    @Override
    public void filterDivIrCurveRefSet(Map map) {

    }

    @Override
    public PageInfo<Map> queryFilterDivIrCurveRefSetByPage(Map map) {
        return null;
    }

    @Override
    public void deleteDivIrCurveList(HashMap<String, Set<String>> map) {
        map.keySet().stream().forEach(vlist->{
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("divCode",vlist);
            Set<String> dateList = map.get(vlist);
            hashMap.put("list",dateList);
            divIrCurveStripMapper.deleteDivIrCurveList(hashMap);
        });
    }

    @Override
    public List<TdivyieldRatesDTO> getLastDivIrCurve(HashMap<String, Set<String>> map, List<TdivyieldRatesDTO> list) {
        map.keySet().stream().forEach(vls->{
            TreeSet<String> set = new TreeSet<>(((o1, o2)->o1.compareTo(o2)));
            set.addAll(map.get(vls));
            // 更新最新的ircCode对应的结束日期改为导入的日期期间中最小的
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("divCode",vls);
            hashMap.put("begDate",set.first());
            divIrCurveStripMapper.updateDivIrCurveByBegDate(hashMap);

            HashMap<String, Object> hashMap2 = new HashMap<>();
            hashMap2.put("divCode",vls);
            hashMap2.put("endDate",set.last());
            String nextDate = divIrCurveStripMapper.getNextDay(hashMap2);
            if (nextDate != null) {
                list.stream().filter(data ->
                        data.getDivCode().equals(vls)&&data.getBegDate().equals(set.last())
                ).forEach(data -> {
                    data.setDivId(0L);
                    data.setEndDate(nextDate);
                    data.setImpDate(DateUtil.format(new Date(),"yyyy-MM-dd"));
                    data.setImpTime(DateUtil.now());
                });
            }else{
                list.stream().forEach(data -> {
                    data.setDivId(0L);
                    data.setEndDate("2050-12-31");
                    data.setImpDate(DateUtil.format(new Date(),"yyyy-MM-dd"));
                    data.setImpTime(DateUtil.now());
                });
            }

        });
        return list;
    }

    @Override
    public boolean insertDivIrCurveList(List<TdivyieldRatesDTO> list) {
        try{
            int insertLength = list.size();
            int i = 0;
            while (insertLength > 600) {
                divIrCurveStripMapper.insertDivIrCurveList(list.subList(i, i + 600));
                i = i + 600;
                insertLength = insertLength - 600;
            }
            if (insertLength > 0) {
                divIrCurveStripMapper.insertDivIrCurveList(list.subList(i, i + insertLength));
            }
        }catch (Exception e){
            return false;
        }
        return true;
    }

    @Override
    public Map getDivCurveByCode(String divCode) {
        Map map = divIrCurveStripMapper.getDivCurveByCode(divCode);
        return map;
    }
    @Override
    @Transactional
    public void allocateDivCurve(Map<String, Object> param) {
        /*****************************权限部分*****************************************/
        ArrayList<String> userPerms = new ArrayList<>();
        ArrayList<String> deptPerms = new ArrayList<>();
        /** 为读写表赋权*/
        //存放创建人所属部门和上级部门，必须写权限
        ArrayList<String> deptAncestors = new ArrayList<>();
        //存放其他部门
        ArrayList<String> anotherDepts = new ArrayList<>();
        //存放其他人的数组
        ArrayList<String> anotherUser = new ArrayList<>();

        Map<String,Object> deptCfgRights = new HashMap<>();
        Map<String,Object> anotherDeptCfgRights = new HashMap<>();
        String allocateDeptAndUsers = param.get("allocateDeptAndUser").toString();
        String userId = String.valueOf(SecurityUtils.getUserId());
        String ircCode = String.valueOf(param.get("divCode"));
        String ircRight = String.valueOf(param.get("divRight"));
        HashMap map= com.alibaba.fastjson2.JSONObject.parseObject( ircRight,HashMap.class);
        //创建人所属部门
        String createDeptId = SecurityUtils.getLoginUser().getSysUser().getDeptId().toString();
        deptAncestors.add(createDeptId);
        //将创建人所属部门的上级部门加入deptPerms
        String deptAncestorIds = divIrCurveStripMapper.getDeptAncestors(createDeptId);
        List<String> deptAncestorIdArrs = Arrays.asList(deptAncestorIds.split(","));
        for (String deptAncestorArr : deptAncestorIdArrs) {
            if ("0".equals(deptAncestorArr) != true) {
                deptPerms.add(deptAncestorArr);
                deptAncestors.add(deptAncestorArr);
            }
        }
        for (String allocateDeptAndUser : allocateDeptAndUsers.split(",")) {
            if (allocateDeptAndUser.charAt(0) == 'u') {
                userPerms.add(allocateDeptAndUser.substring(2));
                if(!userId.equals(allocateDeptAndUser.substring(2))){
                    //不是本人，赋予传过来的权限
                    anotherUser.add(allocateDeptAndUser.substring(2));
                }
            } else if (allocateDeptAndUser.charAt(0) == 'd') {
                deptPerms.add(allocateDeptAndUser.substring(2));
                if(!createDeptId.equals(allocateDeptAndUser.substring(2))){
                    //不是所属部门，赋予传过来的权限
                    anotherDepts.add(allocateDeptAndUser.substring(2));
                }
            }
        }
        // param中放入用户id和部门id，用于后续的tsys_user_perm和tsys_dept_perm
        if (userPerms.size() > 0) {
            param.put("userIds", userPerms);
        }
        if (deptPerms.size() > 0) {
            param.put("deptIds", deptPerms);
        }
        //为创建人单独赋写权限
        List<DivIrCurveDTO>  anotherUserList=new ArrayList<>();
        DivIrCurveDTO userDivRight=new DivIrCurveDTO();
        userDivRight.setUserId(userId);
        userDivRight.setDivCode(ircCode);
        userDivRight.setDivRight("2");
        anotherUserList.add(userDivRight);
        //其他人传过来的权限
        if(anotherUser.size() != 0){
            for (String authId:anotherUser) {
                DivIrCurveDTO anotherSet=new DivIrCurveDTO();
                anotherSet.setUserId(authId);
                anotherSet.setDivCode(ircCode);
                anotherSet.setDivRight(map.get(anotherSet.getUserId()).toString());
                anotherUserList.add(anotherSet);
            }
            divIrCurveStripMapper.batchInsertCurveUser(anotherUserList);
        }
        //为所属部门和上级部门单独赋写权限
        deptCfgRights.put("deptIds",deptAncestors);
        deptCfgRights.put("divCode",ircCode);
        deptCfgRights.put("divRight","2");
        divIrCurveStripMapper.batchInsertCurveDept(deptCfgRights);
        //为其他部门赋传过来的权限
        anotherDepts.removeAll(deptAncestors);
        if(anotherDepts.size() != 0){
            anotherDeptCfgRights.put("deptIds",anotherDepts);
            anotherDeptCfgRights.put("divCode",ircCode);
            anotherDeptCfgRights.put("divRight","2");
            divIrCurveStripMapper.batchInsertCurveDept(anotherDeptCfgRights);
        }

        /** 更新tsys_usr_perm和tsys_dept_perm **/
        divIrCurveStripMapper.updateUserPermDivCurve(param);
        divIrCurveStripMapper.updateDeptPermDivCurve(param);
        /*******************************************************************************/
    }


    @Override
    public void updateCurveUserAuthority(Map<String, Object> params) {
        List<Integer> userIds = (List<Integer>) params.get("userIds");
        String ircRight = String.valueOf(params.get("divRight"));
        String deptId = String.valueOf(params.get("deptId"));
        //存放上级部门
        ArrayList<String> deptAncestors = new ArrayList<>();
        //将创建人所属部门的上级部门加入deptPerms
        String deptAncestorIds = divIrCurveStripMapper.getDeptAncestors(deptId);
        List<String> deptAncestorIdArrs = Arrays.asList(deptAncestorIds.split(","));
        for (String deptAncestorArr : deptAncestorIdArrs) {
            if ("0".equals(deptAncestorArr) != true) {
                deptAncestors.add(deptAncestorArr);
            }
        }
        for(Integer userId : userIds){
            Map<String,Object> param = new HashMap<>();
            param.put("userId",userId);
            param.put("divCode",params.get("divCode"));
            param.put("deptId",deptId);
            param.put("divRight",ircRight);
            if("1".equals(divIrCurveStripMapper.queryDivCurveFlagByUserId(String.valueOf(userId)))){
                //如果tsys_user_flag为1，则改其部门权限
                List<Map> list = divIrCurveStripMapper.queryDivCurveDept(param);
                if (list.size() == 0 && !"0".equals(ircRight)) {
                    //如果原来没有权限且需要权限，直接插入
                    divIrCurveStripMapper.saveDivCurveDept(param);
                } else if(list.size() != 0 && !"0".equals(ircRight)){
                    //如果原本有权限且不是无权限，则修改
                    divIrCurveStripMapper.updateDivCurveDept(param);
                }else if(list.size() != 0 && "0".equals(ircRight)){
                    //如果原本有权限且无权限，直接删除
                    divIrCurveStripMapper.deleteDivCurveDept(param);
                }
                //修改对应dept_id的tsys_dept_perm，先清空
                divIrCurveStripMapper.removeDeptPermCurveByDeptId(param);
                if(!"0".equals(ircRight)) {
                    //先给传过来的部门赋权
                    params.put("deptIds",Arrays.asList(deptId));
                    divIrCurveStripMapper.updateDeptPermDivCurve(params);
                    //给传过来的部门的上级部门赋值
                    Map<String,Object> deptParams = new HashMap<>();
                    deptParams.put("deptIds",deptAncestors);
                    deptParams.put("divCode",params.get("divCode"));
                    deptParams.put("divRight",2);
                    for(String deId : deptAncestors){
                        deptParams.put("deptId",deId);
                        divIrCurveStripMapper.deleteDivCurveDept(deptParams);
                        divIrCurveStripMapper.saveDivCurveDept(deptParams);
                        divIrCurveStripMapper.removeDeptPermCurveByDeptId(deptParams);
                    }
                    if(deptAncestors.size()>0){
                        divIrCurveStripMapper.updateDeptPermDivCurve(deptParams);
                    }
                }
            }else{
                //flag不为1，则直接修改对应用户
                List<Map> list = divIrCurveStripMapper.queryDivCurveUserPerm(param);
                if (list.size() == 0 && !"0".equals(ircRight)) {
                    divIrCurveStripMapper.saveDivCurveUser(param);
                } else if(list.size() != 0 && !"0".equals(ircRight)){
                    divIrCurveStripMapper.updateDivCurveUser(param);
                }else if(list.size() != 0 && "0".equals(ircRight)){
                    divIrCurveStripMapper.deleteDivCurveUser(param);
                }
                divIrCurveStripMapper.removeUserPermDivCurveByUserId(param);
            }
        }
        if(!"0".equals(ircRight)) {
            divIrCurveStripMapper.updateUserPermDivCurve(params);
        }
    }

    public List<DivIrCurveDTO>  checkDivIrCurve(Map<String, Object> params){
       return  divIrCurveStripMapper.checkDivIrCurve(params);
    }
}
